template<typename MUTEX> inline
Condition<MUTEX>::Condition (MUTEX &m)
: mutex_ (m)
, waiters_ (0)
{
#if defined NDK_LINUX
    ::pthread_cond_init (&this->cond_, NULL);
#elif defined NDK_WIN32
    CreateSemaphore(NULL, 0, LONG_MAX, NULL);
#endif
}
template<typename MUTEX> inline
Condition<MUTEX>::~Condition ()
{
#if defined NDK_LINUX
    int retry = 0;
    while ((::pthread_cond_destroy (&this->cond_) == EBUSY) 
            && retry++ < 3)
    {
        this->broadcast ();
        Thread::yield ();
    }
#elif defined NDK_WIN32
    CloseHandle(this->cond_);
#endif
}
template<typename MUTEX> inline
int Condition<MUTEX>::wait ()
{
#if defined NDK_LINUX
    ++this->waiters_;
    int result = ::pthread_cond_wait (&this->cond_,
            const_cast<pthread_mutex_t*>(&this->mutex_.lock ()));
    if (result != 0)
    {
        errno = result;
        result = -1;
    }
    --this->waiters_;
    return result;
#elif defined NDK_WIN32
    return this->wait (0);
#endif
}
#if 0
    struct timespec timeout;
    struct timeval  tp;
    ::gettimeofday (&tp, NULL);
    timeout.tv_sec   = (msec / 1000) + tp.tv_sec;
    timeout.tv_nsec  = ((msec % 1000) * 1000000) + (tp.tv_usec * 1000);
    while (timeout.tv_nsec >= 1000000000)
    {
	timeout.tv_nsec -= 1000000000;
	timeout.tv_sec++;
    }
#endif
template<typename MUTEX> inline
int Condition<MUTEX>::wait (const TimeValue *timeout)
{
#if defined NDK_LINUX
    if (timeout == 0) 
        return this->wait ();

    ++this->waiters_;

    struct timespec ts;
    ts = NDK::gettimeofday () + *timeout;
    // shall not return an error code of [EINTR]
    int result = ::pthread_cond_timedwait (&this->cond_, 
            const_cast<pthread_mutex_t*>(&this->mutex_.lock ()), 
            &ts);
    if (result != 0)
    {
        errno  = result;
        result = -1;
    }
    --this->waiters_;
    return result;
#elif defined NDK_WIN32
    DWORD wait_time = INFINITE;
    if (timeout != 0) 
        wait_time = timeout->msec ();

    int result = 0;
    this->waiter_mutex_.acquire ();
    ++this->waiters_;
    this->waiter_mutex_.release ();

    this->mutex_.release ();

    result = WaitForSingleObject (this->cond_, wait_time);
    if (result != WAIT_OBJECT_0)
        result = -1;

    this->waiter_mutex_.acquire ();
    --this->waiters_;
    this->waiter_mutex_.release ();

    this->mutex_.acquire ();
    return result;
#endif
}
template<typename MUTEX> inline
int Condition<MUTEX>::signal ()
{
#if defined NDK_LINUX
    if (this->waiters_ > 0)
    {
        int result = ::pthread_cond_signal (&this->cond_);
        if (result != 0)
        {
            errno  = result;
            return -1;
        }
    }
    return 0;
#elif defined NDK_WIN32
    this->waiter_mutex_.acquire ();
    int n = this->waiters_;
    this->waiter_mutex_.release ();
    if (n > 0)
        return ReleaseSemaphore(this->cond_, 1, NULL) ? 0 : -1;
    reutrn 0;
#endif
}
template<typename MUTEX> inline
int Condition<MUTEX>::broadcast ()
{
#if defined NDK_LINUX
    if (this->waiters_ > 0)
    {
        int result = ::pthread_cond_broadcast (&this->cond_);
        if (result != 0)
        {
            errno  = result;
            return -1;
        }
    }
    return 0;
#elif defined NDK_WIN32
    this->waiter_mutex_.acquire ();
    int n = this->waiters_;
    this->waiter_mutex_.release ();
    if (n > 0)
        return ReleaseSemaphore(this->cond_, n, NULL) ? 0 : -1;
    reutrn 0;
#endif
}
template<typename MUTEX> inline
MUTEX &Condition<MUTEX>::mutex ()
{
    return this->mutex_;
}

